package com.nali.dal.statement.util.number;

public class NumberOperateUtil {
	public final static NumberHanlder add = new NumberHanlder(new NumberOperate() {
		@Override
		public Number handleDouble(double value1, double value2) {
			return value1 + value2;
		}
		@Override
		public Number handleInteger(int value1, int value2) {
			return value1 + value2;
		}
		@Override
		public Number handleLong(long value1, long value2) {
			return value1 + value2;
		}
	});

	public final static NumberHanlder subtract = new NumberHanlder(new NumberOperate() {
		@Override
		public Number handleDouble(double value1, double value2) {
			return value1 - value2;
		}
		@Override
		public Number handleInteger(int value1, int value2) {
			return value1 - value2;
		}
		@Override
		public Number handleLong(long value1, long value2) {
			return value1 - value2;
		}
	});
	
	public final static NumberHanlder multiply = new NumberHanlder(new NumberOperate() {
		@Override
		public Number handleDouble(double value1, double value2) {
			return value1 * value2;
		}
		@Override
		public Number handleInteger(int value1, int value2) {
			return value1 * value2;
		}
		@Override
		public Number handleLong(long value1, long value2) {
			return value1 * value2;
		}
	});
	
	public final static NumberHanlder divide = new NumberHanlder(new NumberOperate() {
		@Override
		public Number handleDouble(double value1, double value2) {
			return value1 / value2;
		}
		@Override
		public Number handleInteger(int value1, int value2) {
			return value1 / value2;
		}
		@Override
		public Number handleLong(long value1, long value2) {
			return value1 / value2;
		}
	});
	/**
	 * @return 0:double,1:long,2:int
	 */
	public static int numberLevel(Number arg1, Number arg2) {
		int level1 = numberLevel(arg1);
		if(level1==0) {
			return 0;
		}
		int level2 = numberLevel(arg2);
		return Math.min(level1, level2);
	}

	public static int numberLevel(Number number) {
		Class<? extends Number> clazz = number.getClass();
		if(clazz.equals(Double.class) || clazz.equals(Float.class)) {
			return 0;
		} else if(clazz.equals(Long.class)) {
			return 1;
		} else {
			return 2;
		}
	}
	
	public static class NumberHanlder {
		private NumberOperate op;

		public NumberHanlder(NumberOperate op) {
			this.op = op;
		}
		
		public Number cal(int numberLevel, Number arg1, Number arg2) {
			switch (numberLevel) {
			case 0:
				return op.handleDouble(arg1.doubleValue(), arg2.doubleValue());
			case 1:
				return op.handleLong(arg1.longValue(), arg2.longValue());
			case 2:
				return op.handleInteger(arg1.intValue(), arg2.intValue());
			default:
				throw new RuntimeException("won't happen?");
			}
		}
		
	}
}
